package intermouse;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.zip.DataFormatException;

/**
 * @author Sőre András
 * @version 1.0
 * @since 2013-04-16
 * 
 * A main függvény által küldött command sztringek értelmezéséért és végrehajtásáért felelős osztály. 
 */
public class TestCommandParser {
	
	
	static BufferedWriter writer = null;
	
	/**
	 * @param s
	 * Kiír a standard outputra.
	 */
	static void print(String s){
		System.out.println(s);
	}

	/**
	 * @param s
	 * Kiír a standard outputra, és ha van kimeneti fájlnév, akkor oda is.
	 */
	static void log(String s){
		System.out.println(s);
		if(writer!=null){
		try {
			writer.write(s);
			writer.newLine();
		} catch (IOException e) {
			System.out.print("cannot write to file!");
			e.printStackTrace();
		}
		}
	}
	
	/**
	 * @param coordString
	 * @return
	 * @throws NumberFormatException
	 * Visszad koordinátákat int tömb formában egy sztringből.
	 */
	static int[] getCoordinates(String coordString) throws NumberFormatException{
		
		String[] numberStrings=null;
		numberStrings=coordString.split(",");
		
		if(numberStrings!=null && numberStrings.length==2){
			int numbers[]=new int[]{Integer.parseInt(numberStrings[0]),Integer.parseInt(numberStrings[1])};
			if(0<=numbers[0] && numbers[0]<=39 && 0<=numbers[1] && numbers[1]<=59)
			return numbers;
		}	
		throw new NumberFormatException();
	}
	

	/**
	 * @param command
	 * @param level
	 * Feltördeli és értelmezi a paraméterként kapott sztringet, és végrehajtja a paraméterként kapott Level-en.
	 */
	static void interpret(String command, Level level){
		
		String[] commands = new String[]{"exit"};

		if(command!=null)
		commands = command.split(" ");
		
//			A parancsok értelmezése a szavak száma alapján csoportosítva
			if(commands.length==1){
				if(commands[0].toLowerCase().equals("exit")){
					try {
						if (writer != null) writer.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (Exception e) {
						e.printStackTrace();
					}
					print("exiting...");
					System.exit(0);
				}
				else if(commands[0].toLowerCase().equals(""))
					print("awaiting orders ;)");
				else if(commands[0].toLowerCase().equals("init")){
					level.init();
					log("Level is now replaced with an init’d one.");
					}
				else
					print("invalid input >:[");
			}
			else if(commands.length==2){
				if(commands[0].toLowerCase().equals("step") ){
					try {
						int number = Integer.parseInt(commands[1].toLowerCase());
						//System.out.println(number);
						for(int i=0; i<number; i++)
							level.makeStep();
							log("Made " + number + " steps.");
					} catch (NumberFormatException e) {
						print("invalid number!");
					}
				}
				else if(commands[0].toLowerCase().equals("showobjects")){
					try {
						int[] coords = getCoordinates(commands[1].toLowerCase());
						int writtenLines = 0;
						for(FieldObject i : level.getFields().get(coords[0]*60+coords[1]).getObj())
						if (i.dead == false)
						{
							log("Object is a(n) "+ i.getClass().getSimpleName() +" at"+" "+coords[0]+","+coords[1]+".");
							writtenLines++;
						}
						for(Smell i : level.getFields().get(coords[0]*60+coords[1]).getSmells())
						{
							log("Object is a(n) "+ i.getClass().getSimpleName() +" at"+" "+coords[0]+","+coords[1]+".");
							writtenLines++;
						}
						
						if (writtenLines == 0)
						{
							log("Empty field at "+coords[0]+","+coords[1]+".");
						}
						
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				else
					print("invalid input >:[");
			}
			else if(commands.length==3){
				if(commands[0].toLowerCase().equals("spawn")){
					
					try {
						int[] coords = getCoordinates(commands[2]);
						Field f=level.getFields().get(coords[0]*60+coords[1]);
						
						if(commands[1].toLowerCase().equals("ant")){
							Ant ant=new Ant(); 
							ant.setField(f);
							level.addAnt(ant);
						}else if(commands[1].toLowerCase().equals("ant")){
							AntEater a = new AntEater(); a.spawn(f); level.addToMaliciousList(a); 
						}else if(commands[1].toLowerCase().equals("anthill")){ AntHill ah = new AntHill(); ah.setField(f); level.setAntHill(ah); 
						}else if(commands[1].toLowerCase().equals("antlion")){ AntLion b = new AntLion(); b.spawn(f); level.addToMaliciousList(b); 
						}else if(commands[1].toLowerCase().equals("food")){ new Food().setField(f);
						}else if(commands[1].toLowerCase().equals("poison")){level.addPoison(f); 
						}else if(commands[1].toLowerCase().equals("stone")){ new Stone().setField(f);
						}else if(commands[1].toLowerCase().equals("water")){ new Water().setField(f);
						}else if(commands[1].toLowerCase().equals("edge")){ new Edge().setField(f); 
						
						}else if(commands[1].toLowerCase().equals("antsmell")){f.addSmell(new AntSmell());
						}else if(commands[1].toLowerCase().equals("antfoodsmell")){f.addSmell(new FoodSmell());
						
						}else throw new DataFormatException("invalid classname!");	
						//hogy ne legyen casesensitive
						log("Spawned "+ (commands[1].substring(0,1).toUpperCase()+commands[1].substring(1,commands[1].length()) )
							+ " at" + " "+coords[0]+","+coords[1]+"." );
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					}catch(DataFormatException e){
						print(e.getMessage());
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				else if(commands[0].toLowerCase().equals("spray")){
					try {
						int[] coords = getCoordinates(commands[2]);
						
						if(commands[1].toLowerCase().equals("deodorant")){
							level.getFields().get(coords[0]*60+coords[1]).applyAntDeodorant(3);
						}
						else if(commands[1].toLowerCase().equals("killer"))
							level.addPoison(level.getFields().get(coords[0]*60+coords[1]));
						else
							throw new DataFormatException("invalid spray type!");
						
						log("Used "+ commands[1]+" at" + " "+coords[0]+","+coords[1]+".");
						
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					} catch (DataFormatException e) {
						print(e.getMessage());
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				else if(commands[0].toLowerCase().equals("activate") && commands[1].toLowerCase().equals("anteater")){
					try {
						
						int[]coords = getCoordinates(commands[2]);
						
						for(FieldObject f : level.getFields().get(coords[0]*60+coords[1]).getObj())
						{
							if(f.getClass()==AntEater.class){
								AntEater e = (AntEater)f;
								e.spawn(level.getFields().get(coords[0]*60+coords[1]));
								log("Activated AntEater at "+coords[0]+","+coords[1]+".");
							}
								
						}
						
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				else
					print("invalid input >:[");
			}
			else if(commands.length==4){
				if(commands[0].toLowerCase().equals("move")){
					
					Field actualField = null;
					ArrayList<Field> backupFields = null;
					
					try {
						int[] targetCoords = getCoordinates(commands[2]);
						int[] coords = getCoordinates(commands[2]);
						int tmpdirection = 0;
						
						if(commands[3].toLowerCase().equals("n")) {
						
							tmpdirection = 0;
							if (targetCoords[0] % 2 == 1)
								targetCoords[0]--;
							else {
								targetCoords[0]--;
								targetCoords[1]++;
							}
						
						}else if(commands[3].toLowerCase().equals("ne")){
							tmpdirection = 1;
							targetCoords[1]++;
							
						}else if(commands[3].toLowerCase().equals("se")){ 
							tmpdirection = 2;
							if (targetCoords[0] % 2 == 1)
								targetCoords[0]++;
							else {
								targetCoords[0]++;
								targetCoords[1]++;
							}
							
						}else if(commands[3].toLowerCase().equals("s")){
							tmpdirection = 3;
							if (targetCoords[0] % 2 == 1) {
								targetCoords[0]++;
								targetCoords[1]--;
							} else
								targetCoords[0]++;
							
						}else if(commands[3].toLowerCase().equals("sw")){
							tmpdirection = 4;
								targetCoords[1]--;
							
						}else if(commands[3].toLowerCase().equals("nw")){
							tmpdirection = 5;
							if (targetCoords[0] % 2 == 1) {
								targetCoords[0]--;
								targetCoords[1]--;
							} else
								targetCoords[0]--;							
						}else
							throw new DataFormatException("invalid direction!");
						
						
						if (!(0 <= targetCoords[0] && targetCoords[0] <= 39
								&& 0 <= targetCoords[1] && targetCoords[1] <= 59))
							throw new DataFormatException("invalid direction!");
						
						
						actualField=level.getFields().get((coords[0]*60+coords[1]));
						backupFields=new ArrayList<Field>(actualField.getAdjacentFields());
						actualField.getAdjacentFields().clear();
						
						for(int i=0; i<6; i++)
							actualField.getAdjacentFields().add(level.getFields().get(targetCoords[0]* 60 + targetCoords[1]));
						
						
						Ant testAnt=null;
						AntEater testAntEater=null;
						
						if(commands[1].toLowerCase().equals("ant")) {
							
							for(FieldObject i : level.getFields().get(coords[0]* 60 + coords[1]).getObj())
								if(i.getClass()==Ant.class){
									testAnt = (Ant)i;
									testAnt.beginRound();
								}
							
						}
						else if(commands[1].toLowerCase().equals("anteater")) {
							for(FieldObject i : level.getFields().get(coords[0]* 60 + coords[1]).getObj())	
								if(i.getClass()==AntEater.class){
									testAntEater = (AntEater)i;
									testAntEater.OVERRIDEDIRECTION(tmpdirection);
									testAntEater.beginRound();
								}
														
						}else	
						throw new DataFormatException("invalid classname!");
							        
						
	
					if(testAnt==null && testAntEater==null)
						throw new DataFormatException("FieldObject not found!");
					
					
					log("Moved "+commands[1]+" from"+ " "+coords[0]+","+coords[1]+" to "+commands[3].toUpperCase()+"."  );
						
					} catch (NumberFormatException e) {
						print("invalid coordinates!");
						e.printStackTrace();
					} catch (DataFormatException e) {
						print(e.getMessage());
					} catch (Exception e) {
						e.printStackTrace();
					}
					actualField.getAdjacentFields().clear(); 
					actualField.getAdjacentFields().addAll(backupFields);
					
				}
				else
					print("invalid input >:[");
			}
			else
				print("invalid input >:[");
	}
	
}
